package com.flower.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.flower.domain.entity.Category;
import com.flower.domain.entity.Order;
import com.flower.domain.entity.OrderItem;
import com.flower.domain.entity.Product;
import com.flower.domain.vo.admin.analysis.ShopCategoryDistributionVO;
import com.flower.domain.vo.admin.analysis.ShopOrderStatusVO;
import com.flower.domain.vo.admin.analysis.ShopSalesTrendVO;
import com.flower.domain.vo.admin.analysis.ShopTopProductsVO;
import com.flower.mapper.CategoryMapper;
import com.flower.mapper.OrderItemMapper;
import com.flower.mapper.OrderMapper;
import com.flower.mapper.ProductMapper;
import com.flower.service.ShopAnalysisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 店铺数据分析服务实现
 */
@Slf4j
@Service
public class ShopAnalysisServiceImpl implements ShopAnalysisService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private OrderItemMapper orderItemMapper;

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private CategoryMapper categoryMapper;

    @Override
    public ShopSalesTrendVO getShopSalesTrend(Integer shopId, String timeRange) {
        // 根据时间范围获取开始和结束时间
        LocalDateTime[] dateRange = getDateRangeByTimeUnit(timeRange);
        LocalDateTime startTime = dateRange[0];
        LocalDateTime endTime = dateRange[1];

        // 获取指定时间范围内的店铺订单
        LambdaQueryWrapper<Order> orderWrapper = new LambdaQueryWrapper<>();
        orderWrapper.eq(Order::getShopId, shopId)
                .ge(Order::getCreateTime, startTime)
                .le(Order::getCreateTime, endTime)
                .in(Order::getStatus, Arrays.asList(1, 2, 3)); // 只统计有效订单：待发货、待收货、已完成

        List<Order> orders = orderMapper.selectList(orderWrapper);

        // 初始化结果对象
        ShopSalesTrendVO result = new ShopSalesTrendVO();
        result.setTotalAmount(0);
        result.setOrderCount(0);
        result.setProductCount(0);

        // 如果没有订单，返回空数据
        if (orders.isEmpty()) {
            result.setDates(new ArrayList<>());
            result.setAmounts(new ArrayList<>());
            result.setCounts(new ArrayList<>());
            return result;
        }

        // 统计总销售金额和订单数量
        int totalAmount = orders.stream().mapToInt(Order::getTotalAmount).sum();
        int orderCount = orders.size();

        // 获取所有订单项，计算商品总数
        List<Integer> orderIds = orders.stream().map(Order::getOrderId).collect(Collectors.toList());
        LambdaQueryWrapper<OrderItem> itemWrapper = new LambdaQueryWrapper<>();
        itemWrapper.in(OrderItem::getOrderId, orderIds);
        List<OrderItem> orderItems = orderItemMapper.selectList(itemWrapper);
        int productCount = orderItems.stream().mapToInt(OrderItem::getQuantity).sum();

        // 按日期分组统计
        Map<LocalDate, List<Order>> ordersByDate = orders.stream()
                .collect(Collectors.groupingBy(order -> order.getCreateTime().toLocalDate()));

        // 生成日期列表、金额列表和数量列表
        List<String> dateList = new ArrayList<>();
        List<Integer> amountList = new ArrayList<>();
        List<Integer> countList = new ArrayList<>();

        // 根据时间范围生成所有日期
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd");
        if ("year".equals(timeRange)) {
            formatter = DateTimeFormatter.ofPattern("yyyy-MM");
        }

        LocalDate currentDate = startTime.toLocalDate();
        while (!currentDate.isAfter(endTime.toLocalDate())) {
            String dateStr = currentDate.format(formatter);
            dateList.add(dateStr);

            // 获取当前日期的订单
            List<Order> dailyOrders = ordersByDate.getOrDefault(currentDate, Collections.emptyList());
            int dailyAmount = dailyOrders.stream().mapToInt(Order::getTotalAmount).sum();
            int dailyCount = dailyOrders.size();

            amountList.add(dailyAmount);
            countList.add(dailyCount);

            // 增加一天
            currentDate = currentDate.plusDays(1);
        }

        // 设置结果
        result.setDates(dateList);
        result.setAmounts(amountList);
        result.setCounts(countList);
        result.setTotalAmount(totalAmount);
        result.setOrderCount(orderCount);
        result.setProductCount(productCount);

        return result;
    }

    @Override
    public ShopOrderStatusVO getShopOrderStatusDistribution(Integer shopId, String timeRange) {
        // 根据时间范围获取开始和结束时间
        LocalDateTime[] dateRange = getDateRangeByTimeUnit(timeRange);
        LocalDateTime startTime = dateRange[0];
        LocalDateTime endTime = dateRange[1];

        // 获取指定时间范围内的店铺订单
        LambdaQueryWrapper<Order> orderWrapper = new LambdaQueryWrapper<>();
        orderWrapper.eq(Order::getShopId, shopId)
                .ge(Order::getCreateTime, startTime)
                .le(Order::getCreateTime, endTime);

        List<Order> orders = orderMapper.selectList(orderWrapper);

        // 初始化结果对象
        ShopOrderStatusVO result = new ShopOrderStatusVO();
        List<ShopOrderStatusVO.OrderStatusItem> statusItems = new ArrayList<>();

        // 定义状态名称映射
        Map<Integer, String> statusNames = new HashMap<>();
        statusNames.put(0, "待付款");
        statusNames.put(1, "待发货");
        statusNames.put(2, "待收货");
        statusNames.put(3, "已完成");
        statusNames.put(4, "已取消");
        statusNames.put(5, "已退款");

        // 统计各状态订单数量
        Map<Integer, Long> statusCounts = orders.stream()
                .collect(Collectors.groupingBy(Order::getStatus, Collectors.counting()));

        // 构建结果
        for (Map.Entry<Integer, String> entry : statusNames.entrySet()) {
            Integer status = entry.getKey();
            String statusName = entry.getValue();
            int count = statusCounts.getOrDefault(status, 0L).intValue();

            // 只添加有订单的状态
            if (count > 0) {
                ShopOrderStatusVO.OrderStatusItem item = new ShopOrderStatusVO.OrderStatusItem();
                item.setStatus(status);
                item.setCount(count);
                item.setStatusName(statusName);
                statusItems.add(item);
            }
        }

        result.setItems(statusItems);
        return result;
    }

    @Override
    public ShopTopProductsVO getShopTopProducts(Integer shopId, String timeRange, Integer limit) {
        // 根据时间范围获取开始和结束时间
        LocalDateTime[] dateRange = getDateRangeByTimeUnit(timeRange);
        LocalDateTime startTime = dateRange[0];
        LocalDateTime endTime = dateRange[1];

        // 获取指定时间范围内的店铺订单
        LambdaQueryWrapper<Order> orderWrapper = new LambdaQueryWrapper<>();
        orderWrapper.eq(Order::getShopId, shopId)
                .ge(Order::getCreateTime, startTime)
                .le(Order::getCreateTime, endTime)
                .in(Order::getStatus, Arrays.asList(1, 2, 3)); // 只统计有效订单：待发货、待收货、已完成

        List<Order> orders = orderMapper.selectList(orderWrapper);

        // 初始化结果对象
        ShopTopProductsVO result = new ShopTopProductsVO();
        List<ShopTopProductsVO.ProductItem> productSalesList = new ArrayList<>();

        // 如果没有订单，返回空数据
        if (orders.isEmpty()) {
            result.setProducts(productSalesList);
            return result;
        }

        // 获取所有订单项
        List<Integer> orderIds = orders.stream().map(Order::getOrderId).collect(Collectors.toList());
        LambdaQueryWrapper<OrderItem> itemWrapper = new LambdaQueryWrapper<>();
        itemWrapper.in(OrderItem::getOrderId, orderIds);
        List<OrderItem> orderItems = orderItemMapper.selectList(itemWrapper);

        // 按商品ID分组，统计销量和销售额
        Map<Integer, List<OrderItem>> itemsByProduct = orderItems.stream()
                .collect(Collectors.groupingBy(OrderItem::getProductId));

        // 统计每个商品的销售情况
        for (Map.Entry<Integer, List<OrderItem>> entry : itemsByProduct.entrySet()) {
            Integer productId = entry.getKey();
            List<OrderItem> items = entry.getValue();

            // 计算销售总额和销售数量
            int salesAmount = items.stream().mapToInt(item -> item.getPrice() * item.getQuantity()).sum();
            int salesCount = items.stream().mapToInt(OrderItem::getQuantity).sum();

            // 获取商品信息
            Product product = productMapper.selectById(productId);
            if (product != null) {
                ShopTopProductsVO.ProductItem productSales = new ShopTopProductsVO.ProductItem();
                productSales.setProductId(productId);
                productSales.setProductName(product.getProductName());
                productSales.setImage(product.getImage());
                productSales.setSalesAmount((long) salesAmount);
                productSales.setSalesCount(salesCount);
                productSalesList.add(productSales);
            }
        }

        // 按销售额排序，并限制返回数量
        productSalesList.sort((a, b) -> b.getSalesAmount().compareTo(a.getSalesAmount()));
        if (productSalesList.size() > limit) {
            productSalesList = productSalesList.subList(0, limit);
        }

        result.setProducts(productSalesList);
        return result;
    }

    @Override
    public ShopCategoryDistributionVO getShopCategoryDistribution(Integer shopId, String timeRange) {
        // 根据时间范围获取开始和结束时间
        LocalDateTime[] dateRange = getDateRangeByTimeUnit(timeRange);
        LocalDateTime startTime = dateRange[0];
        LocalDateTime endTime = dateRange[1];

        // 获取店铺商品
        LambdaQueryWrapper<Product> productWrapper = new LambdaQueryWrapper<>();
        productWrapper.eq(Product::getShopId, shopId);
        List<Product> products = productMapper.selectList(productWrapper);

        // 初始化结果对象
        ShopCategoryDistributionVO result = new ShopCategoryDistributionVO();
        List<ShopCategoryDistributionVO.CategoryItem> categoryItems = new ArrayList<>();

        // 如果没有商品，返回空数据
        if (products.isEmpty()) {
            result.setCategories(categoryItems);
            return result;
        }

        // 按分类分组，统计商品数量
        Map<Integer, List<Product>> productsByCategory = products.stream()
                .collect(Collectors.groupingBy(Product::getCategoryId));

        // 获取所有分类信息
        List<Integer> categoryIds = new ArrayList<>(productsByCategory.keySet());
        LambdaQueryWrapper<Category> categoryWrapper = new LambdaQueryWrapper<>();
        categoryWrapper.in(Category::getCategoryId, categoryIds);
        List<Category> categories = categoryMapper.selectList(categoryWrapper);
        Map<Integer, String> categoryNames = categories.stream()
                .collect(Collectors.toMap(Category::getCategoryId, Category::getCategoryName));

        // 计算总商品数
        int totalProducts = products.size();

        // 构建结果
        for (Map.Entry<Integer, List<Product>> entry : productsByCategory.entrySet()) {
            Integer categoryId = entry.getKey();
            List<Product> categoryProducts = entry.getValue();
            int count = categoryProducts.size();
            double percentage = (double) count / totalProducts * 100;

            ShopCategoryDistributionVO.CategoryItem item = new ShopCategoryDistributionVO.CategoryItem();
            item.setCategoryId(categoryId);
            item.setCategoryName(categoryNames.getOrDefault(categoryId, "未知分类"));
            item.setCount(count);
            item.setPercentage(Math.round(percentage * 100) / 100.0); // 保留两位小数
            categoryItems.add(item);
        }

        // 按数量排序
        categoryItems.sort((a, b) -> b.getCount().compareTo(a.getCount()));

        result.setCategories(categoryItems);
        return result;
    }

    /**
     * 根据时间单位获取日期范围
     * @param timeRange 时间范围：today, week, month, year
     * @return 日期范围数组，索引0为开始时间，索引1为结束时间
     */
    private LocalDateTime[] getDateRangeByTimeUnit(String timeRange) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime startTime;
        LocalDateTime endTime = LocalDateTime.of(now.toLocalDate(), LocalTime.MAX);

        switch (timeRange) {
            case "today":
                startTime = LocalDateTime.of(now.toLocalDate(), LocalTime.MIN);
                break;
            case "week":
                int dayOfWeek = now.getDayOfWeek().getValue();
                startTime = LocalDateTime.of(now.toLocalDate().minusDays(dayOfWeek - 1), LocalTime.MIN);
                break;
            case "year":
                startTime = LocalDateTime.of(now.toLocalDate().withDayOfYear(1), LocalTime.MIN);
                break;
            case "month":
            default:
                startTime = LocalDateTime.of(now.toLocalDate().withDayOfMonth(1), LocalTime.MIN);
                break;
        }

        return new LocalDateTime[]{startTime, endTime};
    }
} 